package com.example.system.service.impl;

import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.common.constant.RedisConstant;
import com.example.common.redis.RedisUtils;
import com.example.common.response.R;
import com.example.common.utils.StringUtils;
import com.example.system.domain.bo.PageBo;
import com.example.system.domain.bo.RoleBo;
import com.example.system.domain.entity.Role;
import com.example.system.domain.vo.PageVo;
import com.example.system.mapper.RoleMapper;
import com.example.system.mapper.UserMapper;
import com.example.system.service.RoleService;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl implements RoleService {
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private UserMapper userMapper;

    /**
     * 获取角色列表-分页
     */
    @Override
    public PageVo getPageVo(PageBo pageBo) {
        List<Role> list = (List<Role>) redisUtils.get(RedisConstant.getList_Role);
        return new PageVo(pageBo, list);
    }

    /**
     * 获取角色列表-缓存搜索
     */
    @Override
    public List<Role> getListRoleKind() {
        List<Role> roles = (List<Role>) redisUtils.get(RedisConstant.getList_Role);
        roles = roles.stream().map(o -> {
            Role role = new Role();
            role.setRoleId(o.getRoleId());
            role.setRoleName(o.getRoleName());
            role.setAccess(o.getAccess());
            return role;
        }).collect(Collectors.toList());
        return roles;
    }

    /**
     * 获取角色列表-数据库搜索
     */
    public List<Role> getAllList() {
        return roleMapper.getList();
    }

    /**
     * 创建角色列表缓存
     */
    @Override
    public void createRoleRedis() {
        List<Role> list = this.getAllList();
        String key = RedisConstant.getList_Role;
        long time = RedisConstant.getList_Role_Time;
        redisUtils.set(key, list, time);
    }

    /**
     * 新增角色
     */
    @Override
    @SneakyThrows
    public String insertRole(RoleBo bo) {
        this.checkRoleBeforeInsert(bo);

        String account = (String) StpUtil.getLoginId();
        Role role = roleMapper.getRoleByAccount(account);
        if (bo.getAccess() < role.getAccess()) {
            LambdaQueryWrapper<Role> lqw = new LambdaQueryWrapper<>();
            lqw.eq(Role::getAccess, bo.getAccess());
            Role role1 = roleMapper.selectOne(lqw);
            //低权限创建高权限角色
            throw new Exception("\"" + role.getRoleName() + "\"无法创建\"" + role1.getRoleName() + "\"权限的角色");
        }


        int userId = userMapper.getUserByAccount(account).getUserId();
        bo.setCreateBy(userId);
        bo.setCreateTime(LocalDateTime.now());
        roleMapper.insertBo(bo);
        createRoleRedis();
        return "添加成功";
    }

    /**
     * 搜索角色列表-分页
     */
    @Override
    public R<PageVo> getPageVoSearch(RoleBo roleBo, PageBo pageBo) {
        String name = roleBo.getRoleName();
        List<Role> roles = (List<Role>) redisUtils.get(RedisConstant.getList_Role);
        if (StringUtils.isNotEmpty(name)) {
            roles = roles.stream().filter(o -> (StringUtils.isNotEmpty(o.getRoleName()) && o.getRoleName().contains(name)) || (StringUtils.isNotEmpty(o.getRemark()) && o.getRemark().contains(name))).collect(Collectors.toList());
        }
        if (StringUtils.isNotEmpty(roles)) {
            return R.ok(new PageVo(pageBo, roles));
        }
        return R.info("没有符合条件的数据", new PageVo());
    }

    /**
     * 修改角色
     */
    @Override
    public String updateRole(RoleBo roleBo) {
        this.checkRoleBeforeUpdate(roleBo);
        roleMapper.updateBo(roleBo);
        createRoleRedis();
        return "修改成功";
    }

    /**
     * 删除角色
     */
    @Override
    public String deleteRole(RoleBo roleBo) {
        roleMapper.deleteBo(roleBo);
        createRoleRedis();
        return "删除成功";
    }

    /**
     * 修改角色前，进行数据检查
     */
    @SneakyThrows
    private void checkRoleBeforeUpdate(Role role) {
        this.checkRole(role);

        List<Role> roles = (List<Role>) redisUtils.get(RedisConstant.getList_Role);
        if (roles.stream().anyMatch(o -> o.getRoleName().equals(role.getRoleName()) && !o.getRoleId().equals(role.getRoleId()))) {
            throw new Exception("数据检查出现异常：权限名称已存在");
        }
        if (roles.stream().anyMatch(o -> o.getAccess().equals(role.getAccess()) && !o.getRoleId().equals(role.getRoleId()))) {
            throw new Exception("数据检查出现异常：权限级别已存在");
        }
    }

    /**
     * 添加角色前，进行数据检查
     */
    @SneakyThrows
    private void checkRoleBeforeInsert(Role role) {
        this.checkRole(role);

        List<Role> roles = (List<Role>) redisUtils.get(RedisConstant.getList_Role);
        if (roles.stream().anyMatch(o -> o.getRoleName().equals(role.getRoleName()))) {
            throw new Exception("数据检查出现异常：权限名称已存在");
        }
        if (roles.stream().anyMatch(o -> Objects.equals(o.getAccess(), role.getAccess()))) {
            throw new Exception("数据检查出现异常：权限级别已存在");
        }
    }

    @SneakyThrows
    private void checkRole(Role role) {
        if (StringUtils.isEmpty(role.getRoleName())) {
            throw new Exception("数据检查出现异常：角色名称为空");
        }
        if (StringUtils.isEmpty(role.getAccess() + "")) {
            throw new Exception("数据检查出现异常：角色级别为空");
        }
        if (role.getAccess() <= 0) {
            throw new Exception("数据检查出现异常：角色权限不能小于等于0");
        }

        List<Role> roles = (List<Role>) redisUtils.get(RedisConstant.getList_Role);
        if (roles.stream().anyMatch(o -> o.getAccess() < role.getAccess() && o.getActivation() < role.getActivation())) {
            throw new Exception("数据检查出现异常：存在权限高于添加权限，且所需活跃度低于添加权限的活跃度！\n建议降低所需活跃度。");
        }
        if (roles.stream().anyMatch(o -> o.getAccess() > role.getAccess() && o.getActivation() > role.getActivation())) {
            throw new Exception("数据检查出现异常：存在权限低于添加权限，且所需活跃度高于添加权限的活跃度！\n建议提高所需活跃度。");
        }
    }

}
